package com.heu.blood.application.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heu.blood.analysis.dao.BloodSampleInfoTransfusionDao;
import com.heu.blood.analysis.dao.BloodTestTransfusionDao;
import com.heu.blood.analysis.entity.BloodSampleInfoTransfusionEntity;
import com.heu.blood.analysis.entity.BloodSampleTransfusionBloodTestVo;
import com.heu.blood.analysis.entity.BloodTestTransfusionEntity;
import com.heu.blood.analysis.service.BloodTestTransfusionService;
import com.heu.blood.application.dao.BloodApplicationDao;
import com.heu.blood.application.dao.BloodApplicationItemDao;
import com.heu.blood.application.dictenum.*;
import com.heu.blood.application.entity.BloodApplicationEntity;
import com.heu.blood.application.entity.BloodApplicationItemEntity;
import com.heu.blood.application.service.BloodApplicationItemService;
import com.heu.blood.application.service.BloodApplicationService;
import com.heu.blood.application.vo.*;
import com.heu.blood.common.Constant.ConstantData;
import com.heu.blood.common.enums.OperateStateEnum;
import com.heu.blood.common.utils.GenerateNumberBySnowFlake;
import com.heu.blood.common.utils.PageUtils;
import com.heu.blood.common.utils.Query;
import com.heu.blood.examine.dao.OperateExamineDao;
import com.heu.blood.examine.dictenum.ReviewTypeEnum;
import com.heu.blood.examine.dictenum.TradeTypeEnum;
import com.heu.blood.examine.entity.OperateExamineEntity;
import com.heu.blood.examine.service.OperateExamineService;
import com.heu.blood.match.dao.BloodMatchDao;
import com.heu.blood.match.dictenum.MatchStateEnum;
import com.heu.blood.match.entity.BloodMatchEntity;
import com.heu.blood.match.entity.PatientInformationEntity;
import com.heu.blood.match.service.BloodMatchService;
import com.heu.blood.security.dao.UserDao;
import com.heu.blood.security.entity.UserEntity;
import com.heu.blood.security.service.UserService;
import com.heu.blood.send.dao.BloodSendDao;
import com.heu.blood.send.entity.BloodSendEntity;
import com.heu.blood.send.service.BloodSendService;
import com.heu.blood.send.vo.BloodInformationAndSendVo;
import com.heu.blood.transfusion.entity.BloodAdverseReactionEntity;
import com.heu.blood.transfusion.service.BloodAdverseReactionService;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.stream.Collectors;


import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;


@Service("bloodApplicationService")
public class BloodApplicationServiceImpl extends ServiceImpl<BloodApplicationDao, BloodApplicationEntity> implements BloodApplicationService {

    @Autowired
    private BloodApplicationItemService bloodApplicationItemService;

    @Autowired
    private BloodApplicationDao bloodApplicationDao;

    @Autowired
    BloodApplicationItemDao bloodApplicationItemDao;

    @Autowired
    OperateExamineService operateExamineService;

    @Autowired
    OperateExamineDao operateExamineDao;

    @Autowired
    BloodTestTransfusionDao bloodTestTransfusionDao;

    @Autowired
    BloodSampleInfoTransfusionDao bloodSampleInfoTransfusionDao;

    @Autowired
    BloodMatchDao bloodMatchDao;

    @Autowired
    BloodSendDao bloodSendDao;

    @Autowired
    BloodTestTransfusionService bloodTestTransfusionService;

    @Autowired
    BloodMatchService bloodMatchService;
//  线程池
    @Autowired
    private ExecutorService executor;

    @Autowired
    private BloodSendService bloodSendService;

    @Autowired
    BloodAdverseReactionService bloodAdverseReactionService;

    @Autowired
    private UserDao userDao;

    @Override
    public PageUtils queryPage(ApplicationSelectVo applicationSelectVo) {
        // 分页信息先搞定
        Map<String,Object> params = new HashMap<>();
        params.put("limit",applicationSelectVo.getLimit());
        params.put("page",applicationSelectVo.getPage());
        LambdaQueryWrapper<BloodApplicationEntity> queryWrapper = Wrappers.lambdaQuery(BloodApplicationEntity.class);

        queryWrapper.ge(applicationSelectVo.getStartTime() != null, BloodApplicationEntity::getGmtCreate, applicationSelectVo.getStartTime())
                .le(applicationSelectVo.getEndTime() != null, BloodApplicationEntity::getGmtCreate, applicationSelectVo.getEndTime())
                .eq(Strings.isNotBlank(applicationSelectVo.getAboBloodType()),BloodApplicationEntity::getAboBloodType,applicationSelectVo.getAboBloodType())
                .like(Strings.isNotBlank(applicationSelectVo.getApplicationId()),BloodApplicationEntity::getApplicationId,applicationSelectVo.getApplicationId())
                .eq(Strings.isNotBlank(applicationSelectVo.getRhBloodType()),BloodApplicationEntity::getRhBloodType,applicationSelectVo.getRhBloodType())
                .eq(Strings.isNotBlank(applicationSelectVo.getApplicationType()),BloodApplicationEntity::getApplicationType,applicationSelectVo.getApplicationType())
                .like(Strings.isNotBlank(applicationSelectVo.getIdCard()),BloodApplicationEntity::getIdCard,applicationSelectVo.getIdCard())
                .eq(Strings.isNotBlank(applicationSelectVo.getApplicationState()),BloodApplicationEntity::getApplicationState,applicationSelectVo.getApplicationState())
                .eq(Strings.isNotBlank(applicationSelectVo.getAppliedDoctorId()),BloodApplicationEntity::getAppliedDoctorId,applicationSelectVo.getAppliedDoctorId())
                .like(Strings.isNotBlank(applicationSelectVo.getPatientName()),BloodApplicationEntity::getPatientName,applicationSelectVo.getPatientName())
                .eq(Strings.isNotBlank(applicationSelectVo.getTransfusionPurpose()),BloodApplicationEntity::getTransfusionPurpose,applicationSelectVo.getTransfusionPurpose())
                .eq(Strings.isNotBlank(applicationSelectVo.getBloodType()),BloodApplicationEntity::getBloodType,applicationSelectVo.getBloodType())
                .eq(Strings.isNotBlank(applicationSelectVo.getPatientId()),BloodApplicationEntity::getPatientId,applicationSelectVo.getPatientId());
                //.ne(BloodApplicationEntity::getVerifyState,OperateStateEnum.REJECT.code());
//        queryWrapper.orderByAsc("CASE WHEN application_type = '" + ApplicationTypeEnum.EMERGENT.code() + "' THEN 0 ELSE 1 END")
//                .orderByDesc(BloodApplicationEntity::getGmtCreate);
        queryWrapper.last("ORDER BY CASE WHEN application_type = '" + ApplicationTypeEnum.EMERGENT.code() + "' THEN 0 ELSE 1 END ASC, gmt_create DESC");
        IPage<BloodApplicationEntity> page = this.page(
                new Query<BloodApplicationEntity>().getPage(params),
                queryWrapper
        );

        List<String> adverseAppIds = bloodAdverseReactionService.listObjs(
                new QueryWrapper<BloodAdverseReactionEntity>().select("application_id").groupBy("application_id"),
                Object::toString
        );

        // 5. 构造返回数据：每条记录用 Map 包装
        List<Map<String, Object>> resultList = page.getRecords().stream().map(app -> {
            Map<String, Object> map = new HashMap<>();
            map.put("application", app);
            map.put("hasAdverseReaction", adverseAppIds.contains(app.getApplicationId()));
            return map;
        }).collect(Collectors.toList());

        // 6. 用 PageUtils 返回封装
        PageUtils resultPage = new PageUtils(page);
        resultPage.setList(resultList); // 替换 list 为 Map 包装后的结果
        return resultPage;

//        return new PageUtils(page);
    }

    @Override
    @Transactional
    public int saveApplication(BloodApplicationVo bloodApplication) {
//        if(StringUtils.isBlank(bloodApplication.getPatientId())
//        || StringUtils.isBlank(bloodApplication.getPatientName())
//        || StringUtils.isBlank(bloodApplication.getClinicalDiagnosis())
//        || StringUtils.isBlank(bloodApplication.getTransfusionPurpose())
//        || StringUtils.isBlank(bloodApplication.getApplicationType())
//        || StringUtils.isBlank(bloodApplication.getAppliedDoctorId())){
//            return 1;
//        }
        // 雪花算法生成的输血id
        GenerateNumberBySnowFlake generateNumberBySnowFlake = new GenerateNumberBySnowFlake(ConstantData.APPLICATION_NO_WORK_ID, ConstantData.APPLICATION_NO_PREFIX);
        BloodApplicationEntity bloodApplicationEntity = new BloodApplicationEntity();
        BeanUtils.copyProperties(bloodApplication,bloodApplicationEntity);
        //设置申请医师名字
        String appliedDoctorId = bloodApplication.getAppliedDoctorId();
        LambdaQueryWrapper<UserEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Strings.isNotBlank(appliedDoctorId), UserEntity::getUserId,appliedDoctorId);
        UserEntity userEntity = userDao.selectOne(queryWrapper);
        String appliedDoctorName = userEntity.getUserName();
        bloodApplicationEntity.setAppliedDoctorName(appliedDoctorName);
        String applicationId = generateNumberBySnowFlake.genNumberByflag();
        bloodApplicationEntity.setApplicationId(applicationId);
        // 默认填入用血申请单
        bloodApplicationEntity.setApplicationState(ApplicationStateEnum.BLOOD_APPLICATION.code());
        bloodApplicationEntity.setVerifyState(ApplicationVerifyStateEnum.IN_VERIFY.code());

        // 获取所有上送的输血条目并设置输血id
        List<BloodApplicationItemEntity> applicationItems = bloodApplication.getApplicationItems();
        for(BloodApplicationItemEntity item : applicationItems){
            item.setApplicationId(applicationId);
            item.setMatchState(MatchStateEnum.UNMATCHED.code());
            // 已发血量设置为0
            item.setSentPartBlood(new BigDecimal(0));
        }
        // 批量保存并设置是否为单一类型申请单
        bloodApplicationItemService.saveBatch(applicationItems);
        if(applicationItems.size() > 1){
            bloodApplicationEntity.setIsSingle(0);
        }else{
            bloodApplicationEntity.setIsSingle(1);
        }

        List<OperateExamineEntity> examineEntities = bloodApplication.getExamineEntities();
        for(int i = 1;i <= examineEntities.size();i++ ){
            OperateExamineEntity cur = examineEntities.get(i - 1);
            // 在这里把所有的内容进行排号并且设置好下一个节点的编号
            if(i == examineEntities.size()){
                cur.setNextIndex(Integer.MAX_VALUE);
            }else{
                cur.setNextIndex(i + 1);
            }
            cur.setExamineIndex(i);
            // 设置交易类型
            cur.setTradeType(TradeTypeEnum.BLOOD_APPLICATION.code());
            // 交易id也要设置进去
            cur.setTradeId(applicationId);
            // 设置状态为待处理
            cur.setOperateState(OperateStateEnum.WAIT.code());
        }
        // 一起塞进去就完事了
        operateExamineService.saveBatch(examineEntities);

        // 把第一条数据对应的血液相关信息塞到里面
        BeanUtils.copyProperties(applicationItems.get(0),bloodApplicationEntity);
        this.save(bloodApplicationEntity);
        return 0;
    }

    @Override
    @Transactional
    public BloodApplicationVo applicationInfo(String applicationId) {
        BloodApplicationVo res = new BloodApplicationVo();
        // 根据applicationId查询出来本条申请单信息
        LambdaQueryWrapper<BloodApplicationEntity> applicationWrapper = new LambdaQueryWrapper<>();
        applicationWrapper.eq(Strings.isNotBlank(applicationId),BloodApplicationEntity::getApplicationId,applicationId);
        BloodApplicationEntity applicationRes = bloodApplicationDao.selectOne(applicationWrapper);
        BeanUtils.copyProperties(applicationRes,res);
        LambdaQueryWrapper<BloodApplicationEntity> historyWrapper = new LambdaQueryWrapper<>();
        historyWrapper.eq(BloodApplicationEntity::getHistoryApplicationId, applicationId);
        int count = bloodApplicationDao.selectCount(historyWrapper);

        // 设置 if_operate
        res.setIf_operate(count == 0);
        // 根据applicationId查询出来详细信息
        LambdaQueryWrapper<BloodApplicationItemEntity> applicationItemWrapper = new LambdaQueryWrapper<>();
        applicationItemWrapper.eq(Strings.isNotBlank(applicationId),BloodApplicationItemEntity::getApplicationId,applicationId);
        List<BloodApplicationItemEntity> bloodApplicationItemRes = bloodApplicationItemDao.selectList(applicationItemWrapper);
        // 在这获取所有的申请单审批信息
        LambdaQueryWrapper<OperateExamineEntity> examineWrapper = new LambdaQueryWrapper<>();
        examineWrapper.eq(Strings.isNotBlank(applicationId),OperateExamineEntity::getTradeId,
                applicationId).orderByAsc(OperateExamineEntity::getExamineIndex);
        List<OperateExamineEntity> operateExamineEntities = operateExamineDao.selectList(examineWrapper);
        res.setExamineEntities(operateExamineEntities);

        // 构造最终结果
        res.setApplicationItems(bloodApplicationItemRes);
        return res;
    }

    @Override
    @Transactional
    public int updateApplication(BloodApplicationVo bloodApplication) {
        // 1.在这先把其中一个更新掉，即用血申请单先更新掉
        BloodApplicationEntity bloodApplicationEntity = new BloodApplicationEntity();
        BeanUtils.copyProperties(bloodApplication,bloodApplicationEntity);
        this.updateById(bloodApplicationEntity);
        // 2.在这去更新每一个子项
        List<BloodApplicationItemEntity> applicationItems = bloodApplication.getApplicationItems();
        for(BloodApplicationItemEntity item : applicationItems){
            BloodApplicationItemEntity byId = bloodApplicationItemService.getById(item);
            if(byId == null){
                // 把申请的id给附着上
                item.setApplicationId(bloodApplication.getApplicationId());
                bloodApplicationItemService.save(item);
            }else{
                bloodApplicationItemService.updateById(item);
            }
        }

        // 3.在这里需要更新全部的审批项
        LambdaQueryWrapper<OperateExamineEntity> examineWrapper = new LambdaQueryWrapper<>();
        examineWrapper.eq(Strings.isNotBlank(bloodApplication.getApplicationId()),OperateExamineEntity::getTradeId,
                bloodApplication.getApplicationId()).orderByAsc(OperateExamineEntity::getExamineIndex);
        // 3.1查询到全部的审批项
        List<OperateExamineEntity> operateExamineEntities = operateExamineDao.selectList(examineWrapper);
        // 3.2获取全部上送来的审批项
        List<OperateExamineEntity> examineEntities = bloodApplication.getExamineEntities();
        List<OperateExamineEntity> finalExamineEntities = new ArrayList<>();
        for(OperateExamineEntity examineEntity : examineEntities){
            boolean flag = true; // true的含义是当前实体是需要新增的
            for(OperateExamineEntity operateExamineEntity : operateExamineEntities){
                // 只要是二者的审核类型相同，同时审核状态都是未审核，那么就更新
                if(examineEntity.getReviewType().equals(operateExamineEntity.getReviewType())
                && operateExamineEntity.getOperateState().equals(OperateStateEnum.WAIT.code())){
                    // 更新下审核人和审核人id
                    operateExamineEntity.setOperatorName(examineEntity.getOperatorName());
                    operateExamineEntity.setOperatorId(examineEntity.getOperatorId());
                    finalExamineEntities.add(operateExamineEntity);
                    flag = false;
                    break;
                }
            }
            if(flag){
                examineEntity.setTradeType(TradeTypeEnum.BLOOD_APPLICATION.code());
                // 交易id也要设置进去
                examineEntity.setTradeId(bloodApplication.getApplicationId());
                // 设置状态为待处理
                examineEntity.setOperateState(OperateStateEnum.WAIT.code());
                finalExamineEntities.add(examineEntity);
            }
        }
        // 批量更新或者保存
        operateExamineService.saveOrUpdateBatch(finalExamineEntities);

        return 0;
    }

    @Override
    @Transactional
    public int removeApplicationAndItemsByIds(List<BloodApplicationEntity> bloodApplications) {
        if(bloodApplications.size() == 0){
            return 1;
        }
        List<Long> deleteIds = new ArrayList<>();
        // 构建删除申请详情的wrapper
        LambdaQueryWrapper<BloodApplicationItemEntity> queryWrapper = new LambdaQueryWrapper<>();
        for(int i = 0;i < bloodApplications.size();i++){
            BloodApplicationEntity cur = bloodApplications.get(i);
            deleteIds.add(cur.getId());
            if(i == 0){
                queryWrapper.eq(Strings.isNotBlank(cur.getApplicationId()),BloodApplicationItemEntity::getApplicationId,cur.getApplicationId());
            }else{
                queryWrapper.or().eq(Strings.isNotBlank(cur.getApplicationId()),BloodApplicationItemEntity::getApplicationId,cur.getApplicationId());
            }

        }
        // 根据id删除所有的申请单里面的数据
        this.removeByIds(deleteIds);
        // 根据申请单id删除所有的东西
        bloodApplicationItemDao.delete(queryWrapper);

        return 0;
    }

    @Override
    @Transactional
    public CentFlowResultVo centFlowList(ApplicationSelectVo applicationSelectVo) {
        CentFlowResultVo res = new CentFlowResultVo();
        LambdaQueryWrapper<BloodApplicationEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ge(applicationSelectVo.getStartTime() != null, BloodApplicationEntity::getApplicationTime, applicationSelectVo.getStartTime())
                .le(applicationSelectVo.getEndTime() != null, BloodApplicationEntity::getApplicationTime, applicationSelectVo.getEndTime());
        if(Strings.isNotBlank(applicationSelectVo.getSearchCondition())){
            queryWrapper.eq(true,BloodApplicationEntity::getPatientName,applicationSelectVo.getSearchCondition())
                    .or().eq(true,BloodApplicationEntity::getApplicationId,applicationSelectVo.getSearchCondition());
        }
        // 新增排除REJECT状态
        queryWrapper.ne(BloodApplicationEntity::getVerifyState, OperateStateEnum.REJECT.code());
        // 倒序
        queryWrapper.orderByDesc(BloodApplicationEntity::getGmtCreate);
        // 查出来列表
        List<BloodApplicationEntity> list = this.list(queryWrapper);
        // 查询结果为空
        if(list.size() == 0){
            return res;
        }
        res.setEntities(list);
        // 查出当前选择的
        BloodApplicationEntity curChoose = list.get(0);
        LambdaQueryWrapper<BloodApplicationItemEntity> bloodApplicationItemEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        bloodApplicationItemEntityLambdaQueryWrapper.eq(Strings.isNotBlank(curChoose.getApplicationId()),BloodApplicationItemEntity::getApplicationId,curChoose.getApplicationId());
        List<BloodApplicationItemEntity> bloodApplicationItemEntities = bloodApplicationItemDao.selectList(bloodApplicationItemEntityLambdaQueryWrapper);
        // 赋值好存在的申请单详情项目
        BloodApplicationVo bloodApplicationVo = new BloodApplicationVo();
        BeanUtils.copyProperties(curChoose,bloodApplicationVo);
        bloodApplicationVo.setApplicationItems(bloodApplicationItemEntities);
        res.setChooseEntity(bloodApplicationVo);
        // 查询到所有的审批流程
        LambdaQueryWrapper<OperateExamineEntity> examineWrapper = new LambdaQueryWrapper<>();
        examineWrapper.eq(Strings.isNotBlank(curChoose.getApplicationId()),OperateExamineEntity::getTradeId,
                curChoose.getApplicationId());
        List<OperateExamineEntity> operateExamineEntities = operateExamineDao.selectList(examineWrapper);
        res.setOperateExamineEntities(operateExamineEntities);
        bloodApplicationVo.setExamineEntities(operateExamineEntities);
        return res;
    }

    @Override
    public BloodApplicationVo getApplicationInfo(BloodApplicationVo bloodApplicationVo) {
        BloodApplicationEntity bloodApplicationEntity = bloodApplicationDao.selectById(bloodApplicationVo.getId());
        BeanUtils.copyProperties(bloodApplicationEntity,bloodApplicationVo);

        LambdaQueryWrapper<UserEntity> userWrapper = new LambdaQueryWrapper<>();
        userWrapper.eq(Strings.isNotBlank(bloodApplicationVo.getAppliedDoctorId()), UserEntity::getUserId, bloodApplicationVo.getAppliedDoctorId());
        UserEntity userEntity = userDao.selectOne(userWrapper);
        if (userEntity != null) {
            bloodApplicationVo.setAppliedDoctorName(userEntity.getUserName());
        }
//        // 2. 查询 user_name
//        String appliedDoctorId = bloodApplicationVo.getAppliedDoctorId();
//        if (Strings.isNotBlank(appliedDoctorId)) {
//            UserEntity userEntity = userDao.selectById(appliedDoctorId);
//            if (userEntity != null) {
//                bloodApplicationVo.setAppliedDoctorName(userEntity.getUserName());
//            }
//        }
        // 在这获取所有的申请单项
        LambdaQueryWrapper<BloodApplicationItemEntity> itemWrapper = new LambdaQueryWrapper<>();
        itemWrapper.eq(Strings.isNotBlank(bloodApplicationVo.getApplicationId()),BloodApplicationItemEntity::getApplicationId,
                bloodApplicationVo.getApplicationId());
        List<BloodApplicationItemEntity> bloodApplicationItemEntities = bloodApplicationItemDao.selectList(itemWrapper);
        bloodApplicationVo.setApplicationItems(bloodApplicationItemEntities);
        // 在这获取所有的申请单审批信息
        LambdaQueryWrapper<OperateExamineEntity> examineWrapper = new LambdaQueryWrapper<>();
        examineWrapper.eq(Strings.isNotBlank(bloodApplicationVo.getApplicationId()),OperateExamineEntity::getTradeId,
                bloodApplicationVo.getApplicationId());
        List<OperateExamineEntity> operateExamineEntities = operateExamineDao.selectList(examineWrapper);
        bloodApplicationVo.setExamineEntities(operateExamineEntities);

        return bloodApplicationVo;
    }
//    专门用于申请单生命周期中有关于配血记录相关的内容
    @Override
    public List<BloodApplicationItemVo> getApplicationItemVoInfo(String applicationId) {
        LambdaQueryWrapper<BloodApplicationItemEntity> applicationItemWrapper = new LambdaQueryWrapper<>();
        applicationItemWrapper.eq(Strings.isNotBlank(applicationId),BloodApplicationItemEntity::getApplicationId,applicationId);
        List<BloodApplicationItemEntity> bloodApplicationItemEntities = bloodApplicationItemDao.selectList(applicationItemWrapper);

        List<BloodApplicationItemVo> bloodApplicationItemVos = new ArrayList<>();
        for (BloodApplicationItemEntity entity: bloodApplicationItemEntities) {
            BloodApplicationItemVo bloodApplicationItemVo = new BloodApplicationItemVo();
            BeanUtils.copyProperties(entity,bloodApplicationItemVo);
            List<BloodMatchEntity> bloodMatchEntities = bloodMatchService.selectMatchListWithApplicationItemId(entity.getId());
            bloodApplicationItemVo.setBloodMatchEntityList(bloodMatchEntities);
            bloodApplicationItemVos.add(bloodApplicationItemVo);
        }
        return bloodApplicationItemVos;
    }

    @Override
    public BloodApplicationEntity selectBloodApplicationByApplicationId(String applicationId) {
        if(applicationId == null || "".equals(applicationId)) return null;
        LambdaQueryWrapper<BloodApplicationEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Strings.isNotBlank(applicationId),BloodApplicationEntity::getApplicationId,applicationId);
        BloodApplicationEntity bloodApplicationEntity = bloodApplicationDao.selectOne(queryWrapper);
        return bloodApplicationEntity;
    }

    @Override
    @Transactional
    public int examineAllApplication(BloodApplicationVo bloodApplicationVo) {
        // 设置一下状态时通过，这个更新的是申请单的状态
        LambdaUpdateWrapper<BloodApplicationEntity> updateWrapper1 = new LambdaUpdateWrapper<>();
        updateWrapper1.set(Strings.isNotBlank(bloodApplicationVo.getApplicationId()),BloodApplicationEntity::getVerifyState,ApplicationVerifyStateEnum.PASS.code());
        updateWrapper1.eq(Strings.isNotBlank(bloodApplicationVo.getApplicationId()),BloodApplicationEntity::getApplicationId,bloodApplicationVo.getApplicationId());
        this.update(updateWrapper1);

        // 设置一下状态通过，这个更新的是审批状态里面的内容
        List<OperateExamineEntity> examineEntities = bloodApplicationVo.getExamineEntities();
        for(OperateExamineEntity item : examineEntities){
            item.setOperateState(OperateStateEnum.PASS.code());
        }
        operateExamineService.updateBatchById(examineEntities);
        return 0;
    }

    @Override
    public CenterFlowStatusResultVo getAllCenterFlowStatus(BloodApplicationVo bloodApplicationVo) {
        CenterFlowStatusResultVo res = new CenterFlowStatusResultVo(); // 建立一个结果的VO
        String verifyState = bloodApplicationVo.getVerifyState();
        // 1.如果申请单还没有全部人员审批完成，那么就需要直接返回，并将申请状态置为进行中
        if(ApplicationVerifyStateEnum.PASS.code().equals(verifyState)){
            // 申请状态完成，可以进行下一步，此时检验和配血同时进行
            res.setApply(CenterFlowStatusEnum.SUCCESS.code());
            res.setExam(CenterFlowStatusEnum.FINISH.code());
            res.setMatch(CenterFlowStatusEnum.FINISH.code());
            // 2.随即查询检验内容，看看是不是全都有，全都有就置为成功
            LambdaQueryWrapper<BloodTestTransfusionEntity> testWrapper = new LambdaQueryWrapper<>();
            // 如果没带来样本的编号，那么绝对不可需要查询了
            if(!Strings.isNotBlank(bloodApplicationVo.getBloodSampleInfoTransfusionId())){
                res.setExam(CenterFlowStatusEnum.FINISH.code());
                return res;
            }
            testWrapper.eq(Strings.isNotBlank(bloodApplicationVo.getBloodSampleInfoTransfusionId()),
                    BloodTestTransfusionEntity::getBloodSampleInfoTransfusionId,bloodApplicationVo.getBloodSampleInfoTransfusionId());
            List<BloodTestTransfusionEntity> testList = bloodTestTransfusionDao.selectList(testWrapper);
            if(testList.size() == 0){
                res.setExam(CenterFlowStatusEnum.FINISH.code());
                return res;
            }
            boolean flag = true;
            for(int i = 0;i < testList.size();i++){
                if(testList.get(i).getProjectResult() == null || "".equals(testList.get(i).getProjectResult())){
                    flag = false;
                    break;
                }
            }
            // 如果实验列表不是0并且没有任何没实验完成的，才能设置成功
            if(flag){
                res.setExam(CenterFlowStatusEnum.SUCCESS.code());
            }
            // 3.下面开始设置配血的值
            LambdaQueryWrapper<BloodMatchEntity> matchWrapper = new LambdaQueryWrapper<>();
            matchWrapper.eq(Strings.isNotBlank(bloodApplicationVo.getApplicationId()),
                    BloodMatchEntity::getApplicationId,bloodApplicationVo.getApplicationId());
//            List<BloodApplicationItemEntity> applicationItems = bloodApplicationVo.getApplicationItems();
//            if(applicationItems.size() > 0){
//                matchWrapper.eq(BloodMatchEntity::getBloodApplicationItemId,applicationItems.get(0).getId());
//            }
//            for(BloodApplicationItemEntity entity : applicationItems){
//                matchWrapper.or().eq(BloodMatchEntity::getBloodApplicationItemId,entity.getId());
//            }
            List<BloodMatchEntity> matchList = bloodMatchService.list(matchWrapper);
            // 只要查询出来存在配血记录，那么就返回是完成
            if(matchList.size() > 0){
                res.setMatch(CenterFlowStatusEnum.SUCCESS.code());
            }
            // 4.下面开始发血查询
            LambdaQueryWrapper<BloodSendEntity> sendWrapper = new LambdaQueryWrapper<>();
            sendWrapper.eq(Strings.isNotBlank(bloodApplicationVo.getApplicationId()),
                    BloodSendEntity::getApplicationId,bloodApplicationVo.getApplicationId());
            List<BloodSendEntity> sendList = bloodSendService.list(sendWrapper);
            // 只要查询出来存在发血记录，那么就返回是在进行中
            if(sendList.size() > 0){
                res.setSend(CenterFlowStatusEnum.SUCCESS.code());
                res.setFeedBack(CenterFlowStatusEnum.FINISH .code());
            }
            // 5.下面来补充输血反馈
            LambdaQueryWrapper<BloodAdverseReactionEntity> adverseWrapper = new LambdaQueryWrapper<>();
            adverseWrapper.eq(Strings.isNotBlank(bloodApplicationVo.getApplicationId()),
                    BloodAdverseReactionEntity::getApplicationId,bloodApplicationVo.getApplicationId());
            List<BloodAdverseReactionEntity> adverseList = bloodAdverseReactionService.list(adverseWrapper);
            // 只要查询出来存在发血记录，那么就返回是在进行中
            if(adverseList.size() > 0){
                res.setFeedBack(CenterFlowStatusEnum.SUCCESS.code());
            }

        }else{
            res.setApply(CenterFlowStatusEnum.FINISH.code());
            return res;
        }
        return res;
    }

    @Override
    public BloodApplicationHistoryVo getBloodApplicationHistory(String applicationId) {
        BloodApplicationHistoryVo bloodApplicationHistoryVo = new BloodApplicationHistoryVo();
        if(applicationId == null || "".equals(applicationId)) return null;
// 1.变量名2.querywrapper的实体3.eq里的实体4.dao中的selectOne5.set
        CompletableFuture<Void> applicationFuture = CompletableFuture.runAsync(() -> {
            BloodApplicationVo bloodApplicationVo = this.applicationInfo(applicationId);
            bloodApplicationHistoryVo.setBloodApplication(bloodApplicationVo);
        }, executor);

        CompletableFuture<Void> sampleFuture = CompletableFuture.runAsync(() -> {
            LambdaQueryWrapper<BloodSampleInfoTransfusionEntity> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Strings.isNotBlank(applicationId),BloodSampleInfoTransfusionEntity::getApplicationId,applicationId);
            List<BloodSampleInfoTransfusionEntity> entities = bloodSampleInfoTransfusionDao.selectList(queryWrapper);
            List<BloodSampleTransfusionBloodTestVo> bloodSampleTransfusionBloodTestVos = new ArrayList<>();
            for(BloodSampleInfoTransfusionEntity entity: entities) {
                BloodSampleTransfusionBloodTestVo bloodSampleTransfusionBloodTestVo = new BloodSampleTransfusionBloodTestVo();
                List<BloodTestTransfusionEntity> bloodTestTransfusionEntityList = bloodTestTransfusionService.getBySampleId(entity.getBloodSampleInfoTransfusionId());
                bloodSampleTransfusionBloodTestVo.setBloodTestTransfusionEntityList(bloodTestTransfusionEntityList);
                bloodSampleTransfusionBloodTestVo.setBloodSampleInfoTransfusionEntity(entity);
                bloodSampleTransfusionBloodTestVos.add(bloodSampleTransfusionBloodTestVo);
            }
            bloodApplicationHistoryVo.setBloodSampleInfoTransfusionEntity(bloodSampleTransfusionBloodTestVos);
        }, executor);

        CompletableFuture<Void> matchFuture = CompletableFuture.runAsync(() -> {
//            LambdaQueryWrapper<BloodMatchEntity> queryWrapper = new LambdaQueryWrapper<>();
//            queryWrapper.eq(Strings.isNotBlank(applicationId),BloodMatchEntity::getApplicationId,applicationId);
//            List<BloodMatchEntity> entities = bloodMatchDao.selectList(queryWrapper);
//            List<BloodMatchApplicationItemVo> res = new ArrayList<>();
//            for (BloodMatchEntity entity: entities) {
//                BloodMatchApplicationItemVo bloodMatchApplicationItemVo = new BloodMatchApplicationItemVo();
//                bloodMatchApplicationItemVo.setBloodMatchEntity(entity);
//                Long bloodApplicationItemId = entity.getBloodApplicationItemId();
//                BloodApplicationItemEntity bloodApplicationItemEntity = bloodApplicationItemService.getById(bloodApplicationItemId);
//                bloodMatchApplicationItemVo.setBloodApplicationItemEntity(bloodApplicationItemEntity);
//                res.add(bloodMatchApplicationItemVo);
//            }
            List<BloodApplicationItemVo> applicationItemVoInfo = this.getApplicationItemVoInfo(applicationId);
            bloodApplicationHistoryVo.setBloodMatchApplicationItem(applicationItemVoInfo);
        }, executor);

        CompletableFuture<Void> sendFuture = CompletableFuture.runAsync(() -> {
            LambdaQueryWrapper<BloodSendEntity> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Strings.isNotBlank(applicationId),BloodSendEntity::getApplicationId,applicationId);
            List<BloodSendEntity> entities = bloodSendDao.selectList(queryWrapper);
            bloodApplicationHistoryVo.setBloodSendEntity(entities);
        }, executor);

        try {
            CompletableFuture.allOf(applicationFuture,
                    sampleFuture,
                    matchFuture,
                    sendFuture).get();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return bloodApplicationHistoryVo;
    }

    @Override
    public int setApplicationPrint(String applicationId) {
        BloodApplicationEntity bloodApplicationEntity = this.selectBloodApplicationByApplicationId(applicationId);
        if (bloodApplicationEntity != null) {
            BloodApplicationEntity updatedPrintEntity = new BloodApplicationEntity();
            updatedPrintEntity.setId(bloodApplicationEntity.getId());
//        修改打印状态
            updatedPrintEntity.setIfPrint(Integer.parseInt(ApplicationPrintEnum.PRINT.code()));
            this.updateById(updatedPrintEntity);
            return 0;
        }
        return 1;
    }

    @Override
    public List<BloodInformationAndSendVo> getBloodListUsedWithApplicationId(String applicationId) {
        return bloodSendDao.getBloodListUsedWithApplicationId(applicationId);
    }

    @Override
    public CenterFlowStatusResultVo getAllCenterFlowStatusWithItemId(BloodApplicationVo bloodApplicationVo) {
        CenterFlowStatusResultVo res = new CenterFlowStatusResultVo(); // 建立一个结果的VO
        String verifyState = bloodApplicationVo.getVerifyState();
        // 1.如果申请单还没有全部人员审批完成，那么就需要直接返回，并将申请状态置为进行中
        if(ApplicationVerifyStateEnum.PASS.code().equals(verifyState)){
            // 申请状态完成，可以进行下一步，此时检验和配血同时进行
            res.setApply(CenterFlowStatusEnum.SUCCESS.code());
            res.setExam(CenterFlowStatusEnum.FINISH.code());
            res.setMatch(CenterFlowStatusEnum.FINISH.code());
            // 2.随即查询检验内容，看看是不是全都有，全都有就置为成功
            LambdaQueryWrapper<BloodTestTransfusionEntity> testWrapper = new LambdaQueryWrapper<>();
            // 如果没带来样本的编号，那么绝对不可需要查询了
            if(!Strings.isNotBlank(bloodApplicationVo.getBloodSampleInfoTransfusionId())){
                res.setExam(CenterFlowStatusEnum.FINISH.code());
                return res;
            }
            testWrapper.eq(Strings.isNotBlank(bloodApplicationVo.getBloodSampleInfoTransfusionId()),
                    BloodTestTransfusionEntity::getBloodSampleInfoTransfusionId,bloodApplicationVo.getBloodSampleInfoTransfusionId());
            List<BloodTestTransfusionEntity> testList = bloodTestTransfusionDao.selectList(testWrapper);
            if(testList.size() == 0){
                res.setExam(CenterFlowStatusEnum.FINISH.code());
                return res;
            }
            boolean flag = true;
            for(int i = 0;i < testList.size();i++){
                if(testList.get(i).getProjectResult() == null || "".equals(testList.get(i).getProjectResult())){
                    flag = false;
                    break;
                }
            }
            // 如果实验列表不是0并且没有任何没实验完成的，才能设置成功
            if(flag){
                res.setExam(CenterFlowStatusEnum.SUCCESS.code());
            }
            // 3.下面开始设置配血的值
            LambdaQueryWrapper<BloodMatchEntity> matchWrapper = new LambdaQueryWrapper<>();
            matchWrapper.eq(BloodMatchEntity::getBloodApplicationItemId,bloodApplicationVo.getCurApplicationItemId());
            List<BloodMatchEntity> matchList = bloodMatchService.list(matchWrapper);
            // 3.1需要去判断结果是不是都已经录入完成了，全部录入完成才行
            if(matchList.size() == 0){
                // 如果长度是0，说明压根没配血
                res.setMatch(CenterFlowStatusEnum.FINISH.code());
            }else{
                // 长度大于0了，说明配血了，但是配血要保证结果已经录入了才行
                res.setMatch(CenterFlowStatusEnum.SUCCESS.code());
                for(BloodMatchEntity entity : matchList){
                    // 只要配血记录中存在没有登记结果的，那么就是正在进行中
                    if(!Strings.isNotBlank(entity.getMainSideResult())){
                        res.setMatch(CenterFlowStatusEnum.FINISH.code());
                        break;
                    }
                }
            }
            // 4.下面开始发血查询
            if(matchList.size() > 0){
                // 必须要存在配血记录，才能设置发血状态为进行中
                res.setSend(CenterFlowStatusEnum.FINISH.code());

            }
            BloodApplicationItemEntity curEntity = null;
            for(BloodApplicationItemEntity entity : bloodApplicationVo.getApplicationItems()){
                // 根据申请项id找到申请项详细信息
                if(entity.getId().equals(bloodApplicationVo.getCurApplicationItemId())){
                    curEntity = entity;
                    break;
                }
            }
            if(curEntity != null){
                // 只要是有了赋值 并且申请量是小于等于已发出的那么就设置为ok
                if(curEntity.getApplyCount().compareTo(curEntity.getSentPartBlood()) < 1){
                    res.setSend(CenterFlowStatusEnum.SUCCESS.code());
                }
            }


//            LambdaQueryWrapper<BloodSendEntity> sendWrapper = new LambdaQueryWrapper<>();
//            sendWrapper.eq(BloodSendEntity::getBloodApplicationItemId,bloodApplicationVo.getCurApplicationItemId());
//            List<BloodSendEntity> sendList = bloodSendService.list(sendWrapper);
//            // 只要查询出来存在发血记录，那么就返回是在进行中
//            if(sendList.size() > 0){
//                res.setSend(CenterFlowStatusEnum.FINISH.code());
//            }
//            res.setFeedBack(CenterFlowStatusEnum.FINISH.code());
            // 5.下面来补充输血反馈
            LambdaQueryWrapper<BloodAdverseReactionEntity> adverseWrapper = new LambdaQueryWrapper<>();
            adverseWrapper.eq(BloodAdverseReactionEntity::getBloodApplicationItemId,bloodApplicationVo.getCurApplicationItemId());
            List<BloodAdverseReactionEntity> adverseList = bloodAdverseReactionService.list(adverseWrapper);
            // 只要查询出来存在发血记录，那么就返回是在进行中
            if(adverseList.size() > 0){
                res.setFeedBack(CenterFlowStatusEnum.SUCCESS.code());
            }

        }else{
            res.setApply(CenterFlowStatusEnum.FINISH.code());
            return res;
        }
        return res;
    }

    @Override
    public PageUtils getInfoOrderByIfprintAndTime(ApplicationSelectVo applicationSelectVo) {
            // 分页信息先搞定
            Map<String,Object> params = new HashMap<>();
            params.put("limit",applicationSelectVo.getLimit());
            params.put("page",applicationSelectVo.getPage());
            // 下面处理筛选的信息
            LambdaQueryWrapper<BloodApplicationEntity> queryWrapper = Wrappers.lambdaQuery(BloodApplicationEntity.class);

            queryWrapper.ge(applicationSelectVo.getStartTime() != null, BloodApplicationEntity::getGmtCreate, applicationSelectVo.getStartTime())
                    .le(applicationSelectVo.getEndTime() != null, BloodApplicationEntity::getGmtCreate, applicationSelectVo.getEndTime())
                    .eq(Strings.isNotBlank(applicationSelectVo.getAboBloodType()),BloodApplicationEntity::getAboBloodType,applicationSelectVo.getAboBloodType())
                    .eq(Strings.isNotBlank(applicationSelectVo.getApplicationId()),BloodApplicationEntity::getApplicationId,applicationSelectVo.getApplicationId())
                    .eq(Strings.isNotBlank(applicationSelectVo.getRhBloodType()),BloodApplicationEntity::getRhBloodType,applicationSelectVo.getRhBloodType())
                    .eq(Strings.isNotBlank(applicationSelectVo.getApplicationType()),BloodApplicationEntity::getApplicationType,applicationSelectVo.getApplicationType())
                    .eq(Strings.isNotBlank(applicationSelectVo.getIdCard()),BloodApplicationEntity::getIdCard,applicationSelectVo.getIdCard())
                    .eq(Strings.isNotBlank(applicationSelectVo.getApplicationState()),BloodApplicationEntity::getApplicationState,applicationSelectVo.getApplicationState())
                    .eq(Strings.isNotBlank(applicationSelectVo.getAppliedDoctorName()),BloodApplicationEntity::getAppliedDoctorName,applicationSelectVo.getAppliedDoctorName())
                    .eq(Strings.isNotBlank(applicationSelectVo.getPatientName()),BloodApplicationEntity::getPatientName,applicationSelectVo.getPatientName())
                    .eq(Strings.isNotBlank(applicationSelectVo.getTransfusionPurpose()),BloodApplicationEntity::getTransfusionPurpose,applicationSelectVo.getTransfusionPurpose())
                    .eq(Strings.isNotBlank(applicationSelectVo.getBloodType()),BloodApplicationEntity::getBloodType,applicationSelectVo.getBloodType())
                    .eq(Strings.isNotBlank(applicationSelectVo.getPatientId()),BloodApplicationEntity::getPatientId,applicationSelectVo.getPatientId());
            queryWrapper.orderByAsc(BloodApplicationEntity::getIfPrint)
                    .orderByDesc(BloodApplicationEntity::getGmtCreate);
            IPage<BloodApplicationEntity> page = this.page(
                    new Query<BloodApplicationEntity>().getPage(params),
                    queryWrapper
            );

            return new PageUtils(page);
    }

    @Override
    public int reapplyApplication(BloodApplicationVo bloodApplication) {
        // 雪花算法生成的输血id
        GenerateNumberBySnowFlake generateNumberBySnowFlake = new GenerateNumberBySnowFlake(ConstantData.APPLICATION_NO_WORK_ID, ConstantData.APPLICATION_NO_PREFIX);
        BloodApplicationEntity bloodApplicationEntity = new BloodApplicationEntity();
        BeanUtils.copyProperties(bloodApplication,bloodApplicationEntity);
        //设置申请医师名字
        String appliedDoctorId = bloodApplication.getAppliedDoctorId();
        LambdaQueryWrapper<UserEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Strings.isNotBlank(appliedDoctorId), UserEntity::getUserId,appliedDoctorId);
        UserEntity userEntity = userDao.selectOne(queryWrapper);
        String appliedDoctorName = userEntity.getUserName();
        bloodApplicationEntity.setAppliedDoctorName(appliedDoctorName);
        String applicationId = generateNumberBySnowFlake.genNumberByflag();
        bloodApplicationEntity.setApplicationId(applicationId);
        bloodApplicationEntity.setHistoryApplicationId(bloodApplication.getApplicationId());
        bloodApplicationEntity.setGmtCreate(new Date());
        bloodApplicationEntity.setGmtModified(new Date());
        // 默认填入用血申请单
        bloodApplicationEntity.setApplicationState(ApplicationStateEnum.BLOOD_APPLICATION.code());
        bloodApplicationEntity.setVerifyState(ApplicationVerifyStateEnum.IN_VERIFY.code());

        // 获取所有上送的输血条目并设置输血id
        List<BloodApplicationItemEntity> applicationItems = bloodApplication.getApplicationItems();
        for(BloodApplicationItemEntity item : applicationItems){
            item.setApplicationId(applicationId);
            item.setMatchState(MatchStateEnum.UNMATCHED.code());
            // 已发血量设置为0
            item.setSentPartBlood(new BigDecimal(0));
            item.setGmtCreate(new Date());
            item.setGmtModified(new Date());
        }
        // 批量保存并设置是否为单一类型申请单
        bloodApplicationItemService.saveBatch(applicationItems);
        if(applicationItems.size() > 1){
            bloodApplicationEntity.setIsSingle(0);
        }else{
            bloodApplicationEntity.setIsSingle(1);
        }

        List<OperateExamineEntity> examineEntities = bloodApplication.getExamineEntities();
        for(int i = 1;i <= examineEntities.size();i++ ){
            OperateExamineEntity cur = examineEntities.get(i - 1);
            // 在这里把所有的内容进行排号并且设置好下一个节点的编号
            if(i == examineEntities.size()){
                cur.setNextIndex(Integer.MAX_VALUE);
            }else{
                cur.setNextIndex(i + 1);
            }
            cur.setExamineIndex(i);
            // 设置交易类型
            cur.setTradeType(TradeTypeEnum.BLOOD_APPLICATION.code());
            // 交易id也要设置进去
            cur.setTradeId(applicationId);
            // 设置状态为待处理
            cur.setOperateState(OperateStateEnum.WAIT.code());
            cur.setGmtCreate(new Date());
            cur.setGmtModified(new Date());
        }
        // 一起塞进去就完事了
        operateExamineService.saveBatch(examineEntities);

        // 把第一条数据对应的血液相关信息塞到里面
        BeanUtils.copyProperties(applicationItems.get(0),bloodApplicationEntity);
        this.save(bloodApplicationEntity);
        return 0;
    }
}